package com.xwintop.xJavaFxTool.controller.littleTools;

import com.xwintop.xJavaFxTool.services.littleTools.ImageInfo;
import com.xwintop.xJavaFxTool.services.littleTools.ImageToolService;
import com.xwintop.xJavaFxTool.view.littleTools.ImageToolView;
import com.xwintop.xcore.javafx.FxApp;
import com.xwintop.xcore.javafx.dialog.FxProgressDialog;
import com.xwintop.xcore.javafx.dialog.ProgressTask;
import com.xwintop.xcore.javafx.helper.TableViewHelper;
import com.xwintop.xcore.util.javafx.FileChooserUtil;
import com.xwintop.xcore.util.javafx.JavaFxSystemUtil;
import com.xwintop.xcore.util.javafx.JavaFxViewUtil;
import com.xwintop.xcore.util.javafx.TooltipUtil;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.stage.FileChooser.ExtensionFilter;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 图片工具控制类
 *
 * @author xufeng
 * @author yiding.he@gmail.com
 */

@Getter
@Setter
@Slf4j
public class ImageToolController extends ImageToolView {

    private ImageToolService imageToolService = new ImageToolService(this);

    private ObservableList<ImageInfo> tableData = FXCollections.observableArrayList();//表格数据

    private String[] formatChoiceBoxStrings = new String[]{"原格式", "jpg", "png", "jpeg", "bmp"};//输出格式类型

    private String[] sizeTypeChoiceBoxStrings = new String[]{"固定值px", "百分比%"};//图片压缩大小类型

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        initView();
        initEvent();
    }

    private void initView() {
        initTable();

        formatChoiceBox.getItems().addAll(formatChoiceBoxStrings);
        formatChoiceBox.getSelectionModel().selectFirst();
        sizeTypeChoiceBox.getItems().addAll(sizeTypeChoiceBoxStrings);
        sizeTypeChoiceBox.getSelectionModel().selectFirst();
        JavaFxViewUtil.setSpinnerValueFactory(scaleWidthSpinner, 0, Integer.MAX_VALUE);
        JavaFxViewUtil.setSpinnerValueFactory(scaleHeightSpinner, 0, Integer.MAX_VALUE);
    }

    private void initTable() {
        TableViewHelper.of(tableViewMain)
            .addStrPropertyColumn("文件", ImageInfo::imageFileNameProperty)
            .addStrPropertyColumn("原始大小", ImageInfo::originalSizeTextProperty)
            .addStrPropertyColumn("压缩后大小", ImageInfo::compressedSizeTextProperty)
            .addStrPropertyColumn("压缩比率", ImageInfo::compressionRateProperty)
            .addStrPropertyColumn("图像尺寸", ImageInfo::imageSizeProperty)
            .addStrPropertyColumn("文件路径", ImageInfo::imageFilePathProperty)
        ;

        tableViewMain.setItems(tableData);
    }

    private void initEvent() {
        tableViewMain.setOnMouseClicked(event -> {
            if (event.getButton() == MouseButton.SECONDARY) {
                MenuItem menu_Remove = new MenuItem("移除选中行");
                menu_Remove.setOnAction(event1 -> {
                    tableData.remove(tableViewMain.getSelectionModel().getSelectedItem());
                });
                MenuItem menu_RemoveAll = new MenuItem("移除所有");
                menu_RemoveAll.setOnAction(event1 -> {
                    tableData.clear();
                });
                tableViewMain.setContextMenu(new ContextMenu(menu_Remove, menu_RemoveAll));
            }

            if (event.getButton() == MouseButton.PRIMARY) {
                updateOriginPreview();
                updateResultPreview();
            }
        });
        FileChooserUtil.setOnDrag(outputFolderTextField, FileChooserUtil.FileType.FOLDER);
    }

    private void updateOriginPreview() {
        int selectedIndex = tableViewMain.getSelectionModel().getSelectedIndex();
        if (selectedIndex < 0) {
            return;
        }
        String imagePath = tableData.get(selectedIndex).getImageFilePath();
        showImageView.setImage(new Image("file:" + imagePath));
        showImageView.setFitWidth(showImageView.getImage().getWidth());
        showImageView.setFitHeight(showImageView.getImage().getHeight());
    }

    private void updateResultPreview() {
        int selectedIndex = tableViewMain.getSelectionModel().getSelectedIndex();
        if (selectedIndex < 0) {
            return;
        }
        String imagePath = tableData.get(selectedIndex).getImageFilePath();

        BufferedImage bufferedImage = imageToolService.getThumbnailPreview(imagePath);
        Image image = SwingFXUtils.toFXImage(bufferedImage, null);
        showCompressionImageView.setImage(image);
        showCompressionImageView.setFitWidth(image.getWidth());
        showCompressionImageView.setFitHeight(image.getHeight());
    }

    @FXML
    private void addImageAction(ActionEvent event) throws Exception {
        File file = FileChooserUtil.chooseFile((ExtensionFilter[]) null);
        if (file != null) {
            tableData.add(createImageInfo(file));
            imageToolService.imageCompressionAction(true);
        }
    }

    @FXML
    private void openFolderAction(ActionEvent event) throws Exception {
        File folder = FileChooserUtil.chooseDirectory();
        if (folder != null) {
            loadImageFiles(folder);
            imageToolService.imageCompressionAction(true);
        }
    }

    private void loadImageFiles(File folder) {

        FxProgressDialog fxProgressDialog = FxProgressDialog.create(FxApp.primaryStage, new ProgressTask() {
            @Override
            protected void execute() {
                List<File> imageFiles = new ArrayList<>(FileUtils.listFiles(folder, null, false));
                List<ImageInfo> imageInfos = new ArrayList<>();
                int size = imageFiles.size();
                for (int i = 0; i < size; i++) {
                    File file = imageFiles.get(i);
                    imageInfos.add(createImageInfo(file));
                    updateProgress(i + 1, size);
                }
                tableData.addAll(imageInfos);
            }
        }, "正在扫描文件...");

        // 这里用 showProgressAndWait 是因为后面还有一个后台服务，而且必须等这个执行完毕
        fxProgressDialog.setShowAsPercentage(false);
        fxProgressDialog.showAndWait();
    }

    private ImageInfo createImageInfo(File file) {
        Image image = new Image("file:" + file.getAbsolutePath());
        ImageInfo imageInfo = new ImageInfo();
        imageInfo.setImageFilePath(file.getAbsolutePath());
        imageInfo.setWidth((int) image.getWidth());
        imageInfo.setHeight((int) image.getHeight());
        imageInfo.setOriginalSize((int) file.length());
        return imageInfo;
    }

    @FXML
    private void imageCompressionAction(ActionEvent event) {
        try {
            imageToolService.imageCompressionAction(false);
            TooltipUtil.showToast("图片压缩完成！");
        } catch (IOException e) {
            TooltipUtil.showToast("图片压缩失败：" + e.getMessage());
        }
    }

    @FXML
    private void refreshPreviewAction(ActionEvent event) {
        try {
            imageToolService.imageCompressionAction(true);
            tableViewMain.refresh();
            TooltipUtil.showToast("刷新预览完成！");
        } catch (IOException e) {
            TooltipUtil.showToast("刷新预览失败：" + e.getMessage());
        }
    }

    @FXML
    private void openOutputFolderAction(ActionEvent event) {
        try {
            String outputPath = outputFolderTextField.getText();
            if (StringUtils.isEmpty(outputPath)) {
                List<String> paths = new ArrayList<>();
                for (ImageInfo rowValue : tableData) {
                    File file = new File(rowValue.getImageFilePath());
                    String path = file.getParent();
                    if (!paths.contains(path)) {
                        paths.add(path);
                        JavaFxSystemUtil.openDirectory(path);
                    }
                }
            } else {
                JavaFxSystemUtil.openDirectory(outputPath);
            }
            TooltipUtil.showToast("图片压缩完成：");
        } catch (Exception e) {
            TooltipUtil.showToast("图片压缩失败：" + e.getMessage());
        }
    }

    @FXML
    private void outputFolderAction(ActionEvent event) {
        File folder = FileChooserUtil.chooseDirectory();
        if (folder != null) {
            outputFolderTextField.setText(folder.getPath());
        }
    }
}
